﻿// Demo.cpp : 定义应用程序的入口点。
//

#include "framework.h"
#include "Demo.h"
#include "Scene.h"
#include "MiniOne.h"
#include "CubeActor.h"
#include "DiffuseActor.h"
#include "FbxActor.h"
#include "TextureActor.h"
#include "TriangleActor.h"
#include "ClipPlane.h"
#include "reflection.h"
#include "waterDemo.h"
#include "MultiplePointLightsDemo.h"
#include "DepthBuffer.h"
#include "InstanceDemo.h"
#include "TessellationDemo.h"
#include "ParticleDemo.h"
#include "ShadowMapDemo.h"
#include "projectViewDemo.h"
#include "DeferredShaderDemo.h"
#include "SkinDemo.h"
#include "PixelBlurDemo.h"
#include "AirEffectDemo.h"
#include "voxelDemo.h"

// 全局变量:
HINSTANCE hInst;                                // 
std::string szWindowClass = "MiniOneEngine";            // the main window class name
std::string szTitle = "MiniOneDemo";
INT32 WINDOW_WIDTH = 800;
INT32 WINDOW_HEIGHT = 600;

LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);

// 此代码模块中包含的函数的前向声明:
//
//  函数: MyRegisterClass()
//
//  目标: 注册窗口类。
//
ATOM MyRegisterClass(HINSTANCE hInstance, DWORD nIcon, DWORD nStyle)
{
	WNDCLASSEX wcex;

	wcex.cbSize = sizeof(WNDCLASSEX);

	wcex.style = nStyle;
	wcex.lpfnWndProc = WndProc;
	wcex.cbClsExtra = 0;
	wcex.cbWndExtra = 0;
	wcex.hInstance = hInstance;
	wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(nIcon));
	wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
	wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
	wcex.lpszMenuName = MAKEINTRESOURCE(IDC_DEMO);
	wcex.lpszClassName = szWindowClass.c_str();
	wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(nIcon));

	return RegisterClassEx(&wcex);
}

#define EXPORT_VALUE(value, ...)\
protected:\
	__VA_ARGS__ m_##value; \
public: \
	void set##value(const __VA_ARGS__& nv) { m_##value = nv; } \
	__VA_ARGS__ get##value() const { return m_##value; } 





struct Point
{
	Point()
	{}
	Point(float x, float y)
	{
		this->x = x;
		this->y = y;
	}
	float x, y;

};



float vectorMag(const Point& start, const Point& end)

{

	return sqrtf((start.x - end.x) * (start.x - end.x) +

		(start.y - end.y) * (start.y - end.y));

}



float DotProduct(const Point& cen, const Point& first, const Point& second)
{

	float dx1 = first.x - cen.x;

	float dx2 = second.x - cen.x;

	float dy1 = first.y - cen.y;

	float dy2 = second.y - cen.y;


	return dx1 * dx2 + dy1 * dy2;

}



//假定逆时针为正向

bool SignByCrossProduct(const Point& cen, const Point& first, const Point& second)
{

	float dx1 = first.x - cen.x;

	float dx2 = second.x - cen.x;

	float dy1 = first.y - cen.y;

	float dy2 = second.y - cen.y;



	if (dx1 * dy2 - dy1 * dx2 > 0) return true;

	return false;

}



//夹角范围[-PI, PI]

float Angle(Point cen, Point first, Point second)

{

	float dx1, dx2, dy1, dy2;

	float angle;



	float mag = vectorMag(cen, first) * vectorMag(cen, second);

	angle = (float)acos(DotProduct(cen, first, second) / mag);



	bool sign = SignByCrossProduct(cen, first, second);



	if (!sign) angle = -angle;



	return angle;

}



class sx 
{
public:
	virtual void Test()
	{
		db();
	}
	void db()
	{

	}
	EXPORT_VALUE(value, int);
};

class sxx : public sx
{
public:
	sxx()
	{

	}
	virtual void Test()
	{

	}

	void db()
	{
		a = 10;
	}

private:
	std::list< std::function<void()> > s;
	int a = 0;
};

typedef double(*FUNC)(double);

double func(double d)
{
	return (d);
}

void xtest(int&& a)
{

}

class CSX
{
public:
	void TestX()
	{
		int a = 0;
	}
	virtual void Test()
	{
		int a = 0;
	}
};

class CSXX : public CSX
{
public:
	void TestX()
	{
		int a = 0;
	}
	virtual void Test()
	{
		int a = 0;
	}
};

class CTimerClock
{
public:
	CTimerClock() = default;

	~CTimerClock() = default;

	void begin()
	{
		mStart = std::chrono::high_resolution_clock::now();
	}

	double getTimerSecond()
	{
		return getTimerMicroSec() * 0.000001f;
	}

	double getTimerMilliSec()
	{
		return getTimerMicroSec() * 0.001;
	}

	INT64 getTimerMicroSec()
	{
		return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - mStart).count();
	}


private:
	std::chrono::time_point<std::chrono::high_resolution_clock> mStart;
};

#define START_OXYGEN 10

int add(int* __restrict b, int* __restrict a)
{
	*b = 10;
	*a = 12;
	return *a + *b;
}
CVoxelDemo* pVoxelDemo = nullptr;
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
	_In_opt_ HINSTANCE hPrevInstance,
	_In_ LPWSTR    lpCmdLine,
	_In_ int       nCmdShow)
{
	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(lpCmdLine);
	{
		Point cen = { 0, 0 };
		Point first = { 0, 1 };
		Point second = { 1, 0 };
		float x = Angle(cen, second, first) *180.0f / (float)3.1415926;
		int xf = 0;
	}
	D3DXMATRIX mm;
	mm.m[0][0] = 1;
	mm.m[0][1] = 2;
	mm.m[0][2] = 1;
	mm.m[0][3] = 4;

	mm.m[1][0] = 3;
	mm.m[1][1] = 6;
	mm.m[1][2] = 7;
	mm.m[1][3] = 9;

	mm.m[2][0] = 1;
	mm.m[2][1] = 2;
	mm.m[2][2] = 3;
	mm.m[2][3] = 2;

	mm.m[3][0] = 3;
	mm.m[3][1] = 4;
	mm.m[3][2] = 5;
	mm.m[3][3] = 9;
	CTimerClock tt;
	tt.begin();
	for (int i = 0; i < 30; ++i)
	{

		D3DXMatrixInverse(&mm, nullptr, &mm);
	}
	float xxx =  tt.getTimerMilliSec();


	// TODO: 在此处放置代码。
	{
		D3DXMATRIX  mm, outmm;
		mm.m[0][0] = 1;
		mm.m[0][1] = 2;
		mm.m[0][2] = 1;
		mm.m[0][3] = 4;

		mm.m[1][0] = 3;
		mm.m[1][1] = 6;
		mm.m[1][2] = 7;
		mm.m[1][3] = 9;

		mm.m[2][0] = 1;
		mm.m[2][1] = 2;
		mm.m[2][2] = 3;
		mm.m[2][3] = 2;
		//D3DXMatrixIdentity(&mm);

		D3DXMatrixIdentity(&outmm);
	//	D3DXMatrixRotationX(&mm, 1.5f);
		mm.m[3][0] = 3;
		mm.m[3][1] = 4;
		mm.m[3][2] = 5;
		mm.m[3][3] = 1;
		outmm.m[3][0] = 3;
		outmm.m[3][1] = 13;
		outmm.m[3][2] = 23;
		D3DXVECTOR3 v = { 1, 33, 12};
		D3DXVECTOR3 v2;
		D3DXVECTOR4 v0, v1;
		D3DXVec3Transform(&v1, &v, &mm);
		v2.x = v1.x;
		v2.y = v1.y;
		v2.z = v1.z;
		D3DXMatrixInverse(&mm, NULL, &mm);
		D3DXVec3Transform(&v0, &v2, &mm);
		//Math::matrixRotationX(&outmm, 1.5f);

		outmm *= mm;
		//Vec3F v(1, 33, 12);
		//v = Math::matrixMulVec3(outmm, v);

		D3DXMATRIX mmI;
		D3DXMatrixInverse(&mmI, nullptr, &outmm);
		//v = Math::matrixMulVec3(mmI, v);
		int x = 0;
	}
	std::result_of<FUNC(double)>::type d = func(9.0);
	sx sxxxxx;
	int sxvalue = sxxxxx.getvalue();
	// enqueue and store future
	
	// get result from future
	//auto xs = result.get();
	{
		float m_RenderYawOffset = 0;
		float m_MoveStrafing = -10;
		float m_RotateYaw = 100;
		if (m_MoveStrafing > 0)
		{
			m_RenderYawOffset = m_RotateYaw + 45.0f;
		}
		else if (m_MoveStrafing < 0)
		{
			m_RenderYawOffset = m_RotateYaw - 45.0f;
		}
		if (m_RenderYawOffset > START_OXYGEN) m_RenderYawOffset = START_OXYGEN;
		m_RenderYawOffset = (int)m_RenderYawOffset & START_OXYGEN;

		int c = 0;
	}
	mini::foundation::IsSSE();
	mini::foundation::IsSSE2();
	
	std::vector<mini::CPoint4F> xx;
	xx.resize(2);
	xx[0].x = 10;
	mini::CPoint4F xxr;
	sx* p = new sxx;
	p->Test();
	p->db();


	sxx a[3];// = { 1,2,3,4,5,6 };
	int cccc = countArray(a);
	//sxx havingSameSize[sizeof(mini::foundation::arraySize(a))];
	int c = 0;// cal_size(havingSameSize);
	RECT rc;
	SetRect(&rc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
	AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);
	WINDOW_WIDTH = rc.right - rc.left;
	WINDOW_HEIGHT = rc.bottom - rc.top;
	MyRegisterClass(hInstance, IDI_DEMO, CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW);
	HWND hWnd = CreateWindow(szWindowClass.c_str(), szTitle.c_str(), WS_OVERLAPPEDWINDOW & (~WS_SIZEBOX),
		(GetSystemMetrics(SM_CXSCREEN) - WINDOW_WIDTH) / 2, (GetSystemMetrics(SM_CYSCREEN) - WINDOW_HEIGHT) / 2,
		(rc.right - rc.left), (rc.bottom - rc.top), nullptr, nullptr, hInstance, nullptr);
	if (!hWnd)
	{
		return FALSE;
	}
	ShowWindow(hWnd, TRUE);
	UpdateWindow(hWnd);
	
	//SetWindowLong(hWnd, GWL_STYLE, GetWindowLong(hWnd, GWL_STYLE) & ~WS_CAPTION);
	//SetWindowPos(hWnd, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_DRAWFRAME);
	srand(0);
	mini::CEngine* pEngine = mini::createEngine(hWnd);
	if (pEngine != nullptr)
	{
		//	REGIST_GLOBALFUNCTION_0(void, test );
		{
			D3DXVECTOR3 v0(0, 1, 0);
			D3DXVec3Normalize(&v0, &v0);
			
			D3DXVECTOR3 v1(0, -1, 0);
			D3DXVec3Normalize(&v1, &v1);
			float x = D3DXVec3Dot(&v1, &v0);
			auto fresult = mini::GEngine->threadJoin<double>(func, 45);
		}

		pEngine->onStart();
		pEngine->stopRender();

		CReflection* pDemo = nullptr;
		CWaterDemo* pWaterDemo = nullptr;
		CMulPointLightsDemo* pLights = nullptr;
		CDepthBuff* pDepthBuffer = nullptr;
		CInstanceDemo* pInstance = nullptr;
		CTessellationDemo* pTessellation = nullptr;
		CParticleDemo* pParticle = nullptr;
		CShadowmapDemo* pShadowMap = nullptr;
		CProjectViewDemo* pProjectShadow = nullptr;
		CDeferredShaderDemo* pDeferredShader = nullptr;
		CSkinDemo* pSkinDemo = nullptr;
		CPixelBlurDemo* pPixelBlurDemo = nullptr;
		CAirEffectDemo* pAirEffectDemo = nullptr;

		int demoSimple = 10;
		switch (demoSimple)
		{
		case 14:
		{
			mini::CScene* pWorldScne = pEngine->loadScene("voxel");
			pVoxelDemo = new CVoxelDemo();
			pVoxelDemo->init(pEngine);
			pWorldScne->findActor(nullptr);

		}
		break;
		case 13:
		{
			mini::CScene* pWorldScne = pEngine->loadScene("AirEffect");
			pAirEffectDemo = new CAirEffectDemo();
			pAirEffectDemo->init(pEngine);
		}
		break;
		case  0:
		{
			mini::CScene* pWorldScne = pEngine->loadScene("demo");
			mini::CActor* pAcotor = new mini::CClipPlane;
			pAcotor->initialise("resource/Mesh/Default/cube.m", "resource/Material/clipPlaneMaterial.ma");
			mini::CRenderNode* pRenderNode = pEngine->createRenderNode();
			pRenderNode->bindActor(pAcotor, mini::RendererType::FrontRenderer);
			pEngine->getCurrentScene()->addRenderNode(pRenderNode);
			pAcotor->setPosition(CVector(3, 0.5, -3));
			SafeRelease(pAcotor);
		}
		break;
		case 1:
		{
			mini::CScene* pWorldScne = pEngine->loadScene("demo");
			pDemo = new CReflection(pEngine);
		}
		break;
		case 2:
		{
			mini::CScene* pWorldScne = pEngine->loadScene("waterDemo");
			pWaterDemo = new CWaterDemo();
			pWaterDemo->init(pEngine);
		}
		break;
		case 3:
		{
			mini::CScene* pWorldScne = pEngine->loadScene("MulPointLights");
			pLights = new CMulPointLightsDemo();
			pLights->init(pEngine);
		}
		break;
		case 4:
		{
			mini::CScene* pWorldScne = pEngine->loadScene("DepthBuffer");
			pDepthBuffer = new CDepthBuff();
			pDepthBuffer->init(pEngine);
		}
		break;
		case 5:
		{
			mini::CScene * pWorldScne = pEngine->loadScene("Instance");
			pInstance = new CInstanceDemo();	
			pInstance->init(pEngine);
		}
		break;
		case 6:
		{
			mini::CScene* pWorldScne = pEngine->loadScene("Tessellation");
			pTessellation = new CTessellationDemo();
			pTessellation->init(pEngine);
		}
		break;
		case 7:
		{
			mini::CScene* pWorldScne = pEngine->loadScene("Particle");
			pParticle = new CParticleDemo();
			pParticle->init(pEngine);
		}
		break;
		case 8:
		{
			mini::CScene* pWorldScne = pEngine->loadScene("Shadowmap");
			pShadowMap = new CShadowmapDemo();
			pShadowMap->init(pEngine);
		}
		break;
		case 9:
		{
			mini::CScene* pWorldScne = pEngine->loadScene("ProjectShadow");
			pProjectShadow = new CProjectViewDemo();
			pProjectShadow->init(pEngine);
		}
		break;
		case 10:
		{
			pDeferredShader = new CDeferredShaderDemo();
			pDeferredShader->init(pEngine);
			mini::CScene* pWorldScne = pEngine->loadScene("DeferredShader");
		}
		break;
		case 11:
		{
			mini::CScene* pWorldScne = pEngine->loadScene("Skin");
			pSkinDemo = new CSkinDemo();
			pSkinDemo->init(pEngine);
		}
		break;
		case 12:
		{
			mini::CScene* pWorldScne = pEngine->loadScene("PixelBlur");
			pPixelBlurDemo = new CPixelBlurDemo();
			pPixelBlurDemo->init(pEngine);
		}
		break;
		}

		pEngine->recoverRender();

		pEngine->onRun();

		pEngine->stopRender();

		pEngine->destory();
		switch (demoSimple)
		{
		case 13:
		{
			SafeDelete(pAirEffectDemo);
		}
		break;
		case 1:
		{
			SafeDelete(pDemo);
		}
		break;
		case 2:
		{
			SafeDelete(pWaterDemo);
		}
		break;
		case 3:
		{
			SafeDelete(pLights);
		}
		break;
		case 4:
		{
			SafeDelete(pDepthBuffer);
		}
		break;
		case 5:
		{
			SafeDelete(pInstance);
		}
		break;
		case 6:
		{
			SafeDelete(pTessellation);
		}
		break;
		case 7:
		{
			SafeDelete(pParticle);
		}
		break;
		case 8:
		{
			SafeDelete(pShadowMap);
		}
		break;
		case 9:
		{
			SafeDelete(pProjectShadow);
		}
		break;
		case 10:
		{
			SafeDelete(pDeferredShader);
		}
		break;
		case 11:
		{
			SafeDelete(pSkinDemo);
		}
		break;
		case 12:
		{
			SafeDelete(pPixelBlurDemo);
		}
		break;
		default:
			break;
		}
	}
    return (int) 0;
}

//
//  函数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  目标: 处理主窗口的消息。
//
//  WM_COMMAND  - 处理应用程序菜单
//  WM_PAINT    - 绘制主窗口
//  WM_DESTROY  - 发送退出消息并返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{

	if (nullptr != pVoxelDemo)
	{
		pVoxelDemo->WndProc(message, wParam, lParam);
	}
    switch (message)
    {
    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
            // TODO: 在此处添加使用 hdc 的任何绘图代码...
            EndPaint(hWnd, &ps);
        }
        break;
    case WM_DESTROY:
		mini::GEngine->stopRender();
        PostQuitMessage(0);
        break;
	case WM_QUIT:
		break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

